
<!DOCTYPE html>
<html lang="en" class="loading">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>TCP协议详解 - Hexo</title>
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <meta name="google" content="notranslate" />
    <meta name="keywords" content="Fechin,"> 
    <meta name="description" content="3. TCP协议详解3.1 TCP服务的特点
传输层协议主要有两个：TCP协议和UDP协议。
TCP协议相对于UDP协议的特点是： 面向连接、字节流和可靠传输

使用TCP协议通信的双方必须先建立连,"> 
    <meta name="author" content="John Doe"> 
    <link rel="alternative" href="atom.xml" title="Hexo" type="application/atom+xml"> 
    <link rel="icon" href="/yi-mark-gitee-io/img/favicon.png"> 
    
    
    
    <meta name="twitter:card" content="summary"/>
    <meta name="twitter:title" content="TCP协议详解 - Hexo"/>
    <meta name="twitter:description" content="3. TCP协议详解3.1 TCP服务的特点
传输层协议主要有两个：TCP协议和UDP协议。
TCP协议相对于UDP协议的特点是： 面向连接、字节流和可靠传输

使用TCP协议通信的双方必须先建立连,"/>
    
    
    
    
    <meta property="og:site_name" content="Hexo"/>
    <meta property="og:type" content="object"/>
    <meta property="og:title" content="TCP协议详解 - Hexo"/>
    <meta property="og:description" content="3. TCP协议详解3.1 TCP服务的特点
传输层协议主要有两个：TCP协议和UDP协议。
TCP协议相对于UDP协议的特点是： 面向连接、字节流和可靠传输

使用TCP协议通信的双方必须先建立连,"/>
    
<link rel="stylesheet" href="/yi-mark-gitee-io/css/diaspora.css">

<meta name="generator" content="Hexo 6.0.0"></head>

<body class="loading">
    <span id="config-title" style="display:none">Hexo</span>
    <div id="loader"></div>
    <div id="single">
    <div id="top" style="display: block;">
    <div class="bar" style="width: 0;"></div>
    <a class="iconfont icon-home image-icon" href="javascript:;" data-url="https://yi-mark.gitee.io"></a>
    <div title="播放/暂停" class="iconfont icon-play"></div>
    <h3 class="subtitle">TCP协议详解</h3>
    <div class="social">
        <div>
            <div class="share">
                <a title="获取二维码" class="iconfont icon-scan" href="javascript:;"></a>
            </div>
            <div id="qr"></div>
        </div>
    </div>
    <div class="scrollbar"></div>
</div>

    <div class="section">
        <div class="article">
    <div class='main'>
        <h1 class="title">TCP协议详解</h1>
        <div class="stuff">
            <span>二月 20, 2022</span>
            
  <ul class="post-tags-list" itemprop="keywords"><li class="post-tags-list-item"><a class="post-tags-list-link" href="/yi-mark-gitee-io/tags/TCP-IP/" rel="tag">TCP&#x2F;IP</a></li></ul>


        </div>
        <div class="content markdown">
            <h1 id="3-TCP协议详解"><a href="#3-TCP协议详解" class="headerlink" title="3. TCP协议详解"></a>3. TCP协议详解</h1><h2 id="3-1-TCP服务的特点"><a href="#3-1-TCP服务的特点" class="headerlink" title="3.1 TCP服务的特点"></a>3.1 TCP服务的特点</h2><blockquote>
<p>传输层协议主要有两个：TCP协议和UDP协议。</p>
<p>TCP协议相对于UDP协议的特点是： <strong>面向连接、字节流和可靠传输</strong></p>
</blockquote>
<p>使用TCP协议通信的双方必须先建立连接，然后才能开始数据的读写。TCP的连接是全双工的，即双方的数据读写可以通过一个连接进行。完成数据交换后，通信双方都必须断开连接以释放系统资源</p>
<blockquote>
<p>字节流：应用程序对数据的发送和接收是没有边界限制。即发送端执行的写操作次数和接收端执行的读操作次数之间没有任何数量关系。</p>
</blockquote>
<p>当发送端应用程序连续执行多次写操作时，TCP模块先将这些数据放入TCP发送缓冲端。当TCP模块真正开始发送数据时，发送缓冲区中这些等待发送的数据可能被封装成一个或多个TCP报文段发出。因此，TCP模块发送出的TCP报文段的个数和应用程序执行的写操作次数之间没有固定的数量关系。</p>
<p>当接收端收到一个或多个TCP报文段后，TCP模块将它们携带的应用程序按照TCP报文段的序号一次放入TCP接收缓冲区中，并通知应用程序读取数据。接收端应用程序可以一次性将TCP接收缓冲区中的数据全部读取，也可以分多次读取，这取决于用户指定的应用程序读缓冲区的大小</p>
<p>因此，应用程序执行的读操作次数和TCP模块接收到的TCP报文段个数之间也没有固定的数量关系</p>
<blockquote>
<p>TCP字节流服务和UDP数据报服务的区别</p>
</blockquote>
<p><img src="https://s2.loli.net/2022/02/21/BbNhD2ItQW7qVrG.png" alt="image-20220208223004894"></p>
<ul>
<li>TCP 传输是可靠的。首先，TCP协议采用发送应答机制，即发送端发送的每个TCP报文段都必须得到接收方的应答，才认为这个TCP报文段传输成功</li>
</ul>
<h2 id="3-2-TCP-头部结构"><a href="#3-2-TCP-头部结构" class="headerlink" title="3.2 TCP 头部结构"></a>3.2 TCP 头部结构</h2><h3 id="3-2-1-TCP固定头部结构"><a href="#3-2-1-TCP固定头部结构" class="headerlink" title="3.2.1 TCP固定头部结构"></a>3.2.1 TCP固定头部结构</h3><p><img src="https://s2.loli.net/2022/02/21/C5TXqmpgRt1aF2D.png" alt="image-20220209140334637"></p>
<ul>
<li>16位端口号：告知主机该报文是来自哪里（源端口号）以及传到哪个上层协议或应用程序（目的端口）</li>
<li>32位序号：一次TCP通信（从TCP连接建立到断开）过程中某一个传输方向上的字节流的每个字节的编号</li>
<li>32位确认号：用作对另一方发送来的TCP报文段的响应。其值是收到的TCP报文段的序号值加１。</li>
<li>４位头部长度：标识该TCP头部有多少个３２bit字（4字节）</li>
<li>6位标志位：<ul>
<li>URG标志，表示紧急指针是否有效</li>
<li>ACK标志，表示确认号是否有效，称携带ACK标志的TCP报文段为<strong>确认报文段。</strong></li>
<li>PSH标志，提示接收端应用程序应该立即从TCP接收缓冲区中读走数据，为接收后续数据腾出空间</li>
<li>RST标志，表示要求对方重新建立连接。称携带RST标志的TCP报文段为<strong>复位报文段</strong></li>
<li>SYN标志，表示请求建立一个连接。称携带SYN标志的TCP报文段为<strong>同步报文段</strong></li>
<li>FIN标志，表示通知对方本端要关闭连接了。称携带FIN标志的TCP报文段为<strong>结束报文段</strong></li>
</ul>
</li>
<li>16位窗口大小：是TCP流量控制的一个手段，窗口指的是接收通知窗口。它告诉对方 本端的TCP接收缓冲区还能容纳多少字节，这样对方就可以控制发送数据的速度</li>
<li>16位校验和：有发送端填充，接收端对TCP报文段执行CRC算法以检验TCP报文段在传输过程中是否损坏<ul>
<li>注意：这个检验不仅包括TCP头部，也包括数据部分</li>
</ul>
</li>
<li>16位紧急指针：是一个正的偏移量。它和序号字段的值相加表示最后一个紧急数据的下一字节的序号</li>
</ul>
<h3 id="3-2-2-TCP头部选项"><a href="#3-2-2-TCP头部选项" class="headerlink" title="3.2.2 TCP头部选项"></a>3.2.2 TCP头部选项</h3><blockquote>
<p>典型的TCP头部选项结构</p>
</blockquote>
<p><img src="https://s2.loli.net/2022/02/21/56MhQ3y2imSjCac.png" alt="image-20220209151715767"></p>
<blockquote>
<p>常见的TCP选项有7种</p>
</blockquote>
<p><img src="https://s2.loli.net/2022/02/21/wslPXAyamhcQkR8.png" alt="image-20220209151755101"></p>
<ul>
<li>kind&#x3D;0 ,是选项表结束选项</li>
<li>kind&#x3D;1,是<strong>空操作（nop）选项</strong>，没有特殊含义</li>
<li>kind&#x3D;2,是最大报文段长度选项。TCP连接初始化时，通信双方使用该选项来协商<strong>最大报文段（Max Segment Size，MSS）</strong></li>
<li>kind&#x3D;3, 是<strong>窗口扩大因子选项（wscale）</strong></li>
<li>kind&#x3D;4，是<strong>选择性确认（Selective Acknowledgment，SACK）选项</strong>。SACK技术使TCP模块只重新发送丢失的TCP报文段，不用发送所有未被确认的TCP报文段</li>
<li>kind&#x3D;8 ,是时间戳选项，该选项提供了较为准确的计算通信双方之间的<strong>回路时间（Round Trip Time，RTT）</strong>的方法</li>
</ul>
<h3 id="3-2-3-TCP-中协议和数据报文传输SEQ和ACK"><a href="#3-2-3-TCP-中协议和数据报文传输SEQ和ACK" class="headerlink" title="3.2.3 TCP 中协议和数据报文传输SEQ和ACK"></a>3.2.3 TCP 中协议和数据报文传输SEQ和ACK</h3><p><img src="https://s2.loli.net/2022/02/21/NxLwTc1rBakzAhH.jpg" alt="img"></p>
<p><strong>普通的ack确认报文段，是不占用序号，只有三种情况占用需要，1、syn&#x3D;1，2、fin&#x3D;1，3、携带数据一个字节占用一个序号</strong></p>
<h2 id="3-3-TCP连接的建立和关闭"><a href="#3-3-TCP连接的建立和关闭" class="headerlink" title="3.3 TCP连接的建立和关闭"></a>3.3 TCP连接的建立和关闭</h2><p><img src="https://s2.loli.net/2022/02/21/WOjdFTPsD2RmXIf.png" alt="image-20220210151100786"></p>
<p><img src="https://s2.loli.net/2022/02/21/bvMNm1aZ92EgFiG.png" alt="image-20220210151119397"></p>
<blockquote>
<p>三次握手（建立连接）</p>
</blockquote>
<ul>
<li><p>第一个TCP报文段包含SYN标志，因此它是一个同步报文段。即客户端向服务器端发起连接请求。同时该同步报文段包含一个ISN值为535734930的序号</p>
</li>
<li><p>第二个TCP报文段也是一个同步报文段，同时它发送 自己的INS值为2159701207的序号，并对第一个同步报文段进行确认。确认值为535734931，即第一个同步报文段的序号值+1</p>
</li>
<li><p>第三个TCP报文段是对第二个同步报文段的确认。</p>
</li>
<li><p>至此，TCP连接就建立了。建立TCP连接的这三个步骤称为<strong>TCP三次握手</strong></p>
</li>
</ul>
<blockquote>
<p>四次挥手（关闭连接）</p>
</blockquote>
<ul>
<li><p>第四个TCP报文段包含FIN标志，因此它是一个结束报文段</p>
</li>
<li><p>第五个TCP报文段为确认第四个TCP报文段</p>
</li>
<li><p>第六个TCP报文段同第四个TCP报文段</p>
</li>
<li><p>第七个TCP报文段为确认第六个TCP报文段</p>
</li>
</ul>
<h3 id="3-3-1-半关闭状态"><a href="#3-3-1-半关闭状态" class="headerlink" title="3.3.1 半关闭状态"></a>3.3.1 半关闭状态</h3><blockquote>
<p> TCP连接是全双工的，所以它允许两个方向的数据传输被独立关闭。</p>
</blockquote>
<p>换言之，通信的一端可以发送结束报文段给对方，告诉它本端已经完成了数据的发送，但允许继续接收来自对方的数据，直到对方也发送结束报文段以关闭连接。TCP连接的这种状态称为<strong>半关闭状态</strong></p>
<p><img src="https://s2.loli.net/2022/02/21/bdXUVtCOKkl9EAY.png" alt="image-20220210153354669"></p>
<h3 id="3-3-2-连接超时"><a href="#3-3-2-连接超时" class="headerlink" title="3.3.2 连接超时"></a>3.3.2 连接超时</h3><p>如果客户端访问一个距离它很远的服务器，或者由于网络繁忙，导致服务器对于客户端发送出的同步报文段没有应答，TCP先进行重连（可能执行多次），如果重连仍然无效，则通知应用程序连接超时。</p>
<h2 id="3-4-TCP状态转移"><a href="#3-4-TCP状态转移" class="headerlink" title="3.4 TCP状态转移"></a>3.4 TCP状态转移</h2><p><img src="https://s2.loli.net/2022/02/21/o1ldN2LGXHZbEWm.png" alt="image-20220211201338299"></p>
<ul>
<li>粗虚线表示典型的服务器端连接的状态转移</li>
<li>粗实线表示典型的客户端连接的状态转移</li>
<li>CLOSED是一个假象的起始点</li>
</ul>
<blockquote>
<p>服务器典型状态转移过程</p>
</blockquote>
<ol>
<li>服务器通过listen系统调用进入LISTEN状态，被动等待客户端连接</li>
<li>服务器监听到某个连接请求（收到同步报文段），就将该连接放入内核等待队列中，并向客户端发送带SYN标志的确认报文段<ul>
<li>此时连接处于SYN_RCVD 状态</li>
</ul>
</li>
<li>服务器成功接收到客户端发送回的确认报文段。<ul>
<li>此时连接转移到ESTABLISHED状态（该状态是连接双方能够进行双向数据传输的状态）</li>
</ul>
</li>
</ol>
<ul>
<li>客户端主动关闭连接</li>
</ul>
<ol start="4">
<li>服务器通过返回报文段是连接进入CLOSE_WAIT状态<ul>
<li>该状态表示：等待服务器应用程序关闭连接。</li>
</ul>
</li>
<li>服务器应用程序关闭连接后，使连接进入LAST_ACK状态<ul>
<li>该状态等待客户端报文段的最后一次确认，一旦确认完成，连接就彻底关闭</li>
</ul>
</li>
</ol>
<blockquote>
<p>客户端的典型状态转移过程</p>
</blockquote>
<p><code>以下的连接状态指客户端的状态</code></p>
<ol>
<li>客户端通过connect系统调用主动与服务器建立连接。<ul>
<li>connect系统调用首先给服务器发送一个同步报文段，使连接转移到SYN_SENT状态</li>
</ul>
</li>
<li>connect系统调用可能因为如下两个原因失败返回<ol>
<li>如果connect连接的目标端口不存在（未被任何进程监听）,或者该端口仍被处于TIME_WAIT 状态的连接所占用，则服务器将给客户端发送一个复位报文段，connect调用失败</li>
<li>如果目标端口存在，但connect在超时时间内未收到服务器的确认报文段，则connect调用失败</li>
</ol>
</li>
<li>调用失败使连接立即返回到初始的CLOSED状态，如果客户端成功收到服务器的同步报文段和确认，则connect调用成功返回，连接转移至ESTABLISHED状态</li>
</ol>
<ul>
<li>客户端执行主动关闭</li>
</ul>
<ol start="4">
<li>客户端向服务器发送一个结束报文段，同时进入FIN_WAIT_1状态。<ul>
<li>若此时客户端收到服务器专门用于确认目的的确认报文段，则连接转移至FIN_WAIT_2状态。</li>
<li>当客户端处于FIN_WAIT_2状态时，服务器处于CLOSE_WAIT状态，这一对状态是可能发送半关闭的状态。此时如果服务器也关闭连接（发送结束报文段），则客户端将给予确认并进入TIME_WAIT 状态。</li>
</ul>
</li>
</ol>
<p><img src="https://s2.loli.net/2022/02/21/lyFS5u23ZmL4VcQ.png" alt="image-20220211222536817"></p>
<h3 id="3-4-1-TIME-WAIT状态"><a href="#3-4-1-TIME-WAIT状态" class="headerlink" title="3.4.1 TIME_WAIT状态"></a>3.4.1 TIME_WAIT状态</h3><blockquote>
<p>客户端连接在收到服务器的结束报文段（TCP报文段6）之后，并没有直接进入CLOSED状态，而是转到TIME_WAIT状态。</p>
<p>在这个状态，客户端连接要等待一段为2MSL（Maximum Segment Life，报文段最大生存时间）的时间，才能完全关闭。</p>
</blockquote>
<p>TIME_WAIT状态存在的原因有两点：</p>
<ul>
<li>可靠地终止TCP连接</li>
<li>保证让迟来的TCP报文段有足够的时间被识别并丢弃</li>
</ul>
<h2 id="3-5-复位报文段"><a href="#3-5-复位报文段" class="headerlink" title="3.5 复位报文段"></a>3.5 复位报文段</h2><h3 id="3-5-1-访问不存在的端口"><a href="#3-5-1-访问不存在的端口" class="headerlink" title="3.5.1 访问不存在的端口"></a>3.5.1 访问不存在的端口</h3><p>当客户端程序访问一个不存在的端口时，目标主机将给他发送一个复位报文段。</p>
<p>当客户端程序向服务器的某个端口发起连接，而该端口仍被处于TIME_WAIT状态的连接所占用，客户端程序也将收到复位报文段</p>
<h3 id="3-5-2-异常终止连接"><a href="#3-5-2-异常终止连接" class="headerlink" title="3.5.2 异常终止连接"></a>3.5.2 异常终止连接</h3><p>TCP提供了异常终止一个连接的方法，即给对方发送一个复位报文段，一旦发送了复位报文段，发送端所有排队等待发送的数据都将被丢弃</p>
<h3 id="3-5-3-处理半打开连接"><a href="#3-5-3-处理半打开连接" class="headerlink" title="3.5.3 处理半打开连接"></a>3.5.3 处理半打开连接</h3><blockquote>
<p>服务器（或客户端）关闭或者异常终止了连接，而对方没有接收到结束报文段（比如发生了网络故障）,此时，客户端（或服务器）还维持着原来的连接，而服务器（或客户端）即使重启，也已经没有该连接的任何信息了</p>
</blockquote>
<p>我们将这种状态称为<strong>半打开状态</strong>，处于这种状态的连接称为半打开连接。</p>
<p>如果客户端（或服务器）往处于半打开状态的连接写入数据，则对方将回应一个复位报文段</p>
<h2 id="3-6-TCP交互数据流"><a href="#3-6-TCP交互数据流" class="headerlink" title="3.6 TCP交互数据流"></a>3.6 TCP交互数据流</h2><p>TCP报文段所携带的应用程序数据按照长度分为两种：交互数据和成块数据</p>
<ul>
<li><strong>交互数据</strong>仅包含很少的字节。使用交互数据的应用程序（或协议）对实时性要求高，比如telnet，ssh等</li>
<li><strong>成块数据</strong>的长度则通常为TCP报文段允许的最大数据长度。使用成块数据的应用程序（或协议）对传输效率要求高，比如ftp</li>
</ul>
<blockquote>
<p>TCP 交互数据流</p>
</blockquote>
<p><img src="https://s2.loli.net/2022/02/21/Oy47znMVlxSqADv.png" alt="image-20220212210547239"></p>
<p><img src="https://s2.loli.net/2022/02/21/oGDycBQxK74qFvw.png" alt="image-20220212210156671"></p>
<ul>
<li><p>TCP报文段1由客户端发送服务器，它携带1个字节的应用程序数据，即字母“l”</p>
</li>
<li><p>TCP报文段2是服务器对TCP报文段1的确认，同时回显字母“l”</p>
</li>
<li><p>TCP报文段3是客户端对TCP报文段2的确认。</p>
</li>
<li><p>TCP报文段4~6是针对字母“s”的上述过程。</p>
</li>
<li><p>TCP报文段7传送的2字节数据分别是：客户端键入的回车符和流结束符（EOF）</p>
</li>
<li><p>TCP报文段8携带服务器返回的客户查询的目录的内容（ls命令的输出），包括该目录下文件的文件名及其显示控制参数</p>
</li>
<li><p>TCP报文段9是客户端对TCP报文段8的确认。</p>
</li>
<li><p>TCP报文段10携带的也是服务器返回给客户端的数据。</p>
</li>
<li><p>TCP报文段11是客户端对TCP报文段10的确认</p>
</li>
</ul>
<p>在上述过程中，客户端针对服务器返回的数据所发送的确认报文段（TCP报文段6，9，11）都不携带任何应用程序数据（length 0），而服务器端每次发送的确认报文段的（TCP报文段2，5，8，10）都包含它需要发送的应用程序数据。</p>
<p>服务器的这种处理方式称为<strong>延迟确认</strong>，即它不马上确认上次收到的数据，而是在一段延迟时间后查看本端是否由数据需要发送，如果有，则和确认信息一起发送。</p>
<p>因为服务器对客户请求处理得很快，所以它发送确认报文段的时候总是有数据一起发送。延迟确认可以减少发送TCP报文段的数量。而由于用户的输入速度明显慢于客户端程序的处理速度，所以客户端的确认报文段总是不携带任何应用程序数据</p>
<h2 id="3-7-TCP成块数据流"><a href="#3-7-TCP成块数据流" class="headerlink" title="3.7 TCP成块数据流"></a>3.7 TCP成块数据流</h2><p><img src="https://s2.loli.net/2022/02/21/7YaSuJ8ZCHAW1ME.png" alt="image-20220212214947404"></p>
<p><img src="https://s2.loli.net/2022/02/21/2tCw9aTf7kYrpHu.png" alt="image-20220212215032040"></p>
<p><img src="https://s2.loli.net/2022/02/21/67tifeomsDqH1WO.png" alt="image-20220212215040563"></p>
<p>注意，客户端发送的最后两个TCP报文段17和18，它们分别是对TCP报文段2和16的确认。由此可见，当传输大量大块数据的时候，发送方会连续发送多个TCP报文段，接收方可以一次确认所有这些报文段。发送方在收到上一次确认后，能连续发送多少个TCP报文段是由接收通告窗口（还需要考虑拥塞窗口）的大小决定的。TCP报文段17说明客户端还能接收30084*64字节（该例中窗口扩大因子为6），而在TCP报文段18中，接收通告窗口大小为27317*64字节，即客户端能接收的数据量变小了。这表明客户端的TCP接收缓冲区有更多的数据未被应用出现读取而停留在其中    </p>
<h2 id="3-8-带外数据"><a href="#3-8-带外数据" class="headerlink" title="3.8 带外数据"></a>3.8 带外数据</h2><p>有些传输层协议具有外带（Out Of Band，OOB ）数据的概念，用于迅速通告对方本端发生的重要事件，因此，外带数据比普通数据有更高的优先级，它总该立即被发送，而不论发送缓冲区中是否排队等待发送的普通数据。</p>
<p>外带数据传输可以使用一条独立的传输层连接，也可以映射到传输普通数据的连接中。</p>
<blockquote>
<p>UDP没有实现外带数据传输，TCP也没有真正的外带数据。</p>
</blockquote>
<p>不过TCP利用头部中的紧急指针标志和紧急指针两个字段，给应用程序提供了一种紧急方式。</p>
<blockquote>
<p>TCP 发送带外数据</p>
</blockquote>
<p>假设一个进程已经往某个TCP连接的发送缓冲区中写入了N个字节的普通数据，并等待其发送。在数据发送前，该进程又向这个连接写入了3个字节的外带数据“abc”。此时，待发送的TCP报文段头部将被设置URG标志，并且紧急指针被设置为指向最后一个带外数据的下一个字节</p>
<p><img src="https://s2.loli.net/2022/02/21/2xUaRVCAgi7tI6K.png" alt="image-20220221221050149"></p>
<p>发送端一次发送的多字节的带外数据中只有最后一字节当作带外数据（字母c），而其他数据（a，b）被当作了普通数据。</p>
<blockquote>
<p>TCP接收带外数据</p>
</blockquote>
<p>TCP接收端只有在接收到紧急指针标志的时才检查紧急指针，然后根据紧急指针所指的位置确定带外数据的位置，并将它读入一个特殊的缓存中。这个缓存只有1个字节，称为<strong>带外缓存</strong>。</p>
<p>如果上层应用程序没有及时将带外数据从带外缓存中读出，则后续的带外数据（如果有的话）会覆盖它</p>
<h2 id="3-9-TCP超时重传"><a href="#3-9-TCP超时重传" class="headerlink" title="3.9 TCP超时重传"></a>3.9 TCP超时重传</h2><p>TCP服务必须能够重传 超时时间内未收到确认的TCP报文段。为此，TCP模块未每个TCP报文段都维护了一个重传定时器，该定时器在TCP报文段第一次被发送时启动。如果超时时间内未收到对方的应答，TCP模块将重传TCP报文段并重置定时器。</p>
<blockquote>
<p>案例分析</p>
</blockquote>
<p><img src="https://s2.loli.net/2022/02/21/kfsmgzWHjo6VT49.png" alt="image-20220221223615683"></p>
<p><img src="https://s2.loli.net/2022/02/21/WM1kzHdIc3SBnZj.png" alt="image-20220221223628579"></p>
<p><img src="https://s2.loli.net/2022/02/21/7iSkMJbuN5OqrlH.png" alt="image-20220221223640449"></p>
<ul>
<li>TCP报文段1~3是三次握手建立连接的过程</li>
<li>TCP报文段4~5是客户端发送数据“1234”（应用程序数据长度为6，包括回车、换行两个字符，后同）及服务器确认的过程</li>
<li>TCP报文段6是客户端第一次发送数据“12”的过程<ul>
<li>因为服务器的网线断开，所以客户端无法收到TCP6的确认报文段</li>
</ul>
</li>
<li>TCP报文段7~11是客户端对TCP报文段6执行了5次重传</li>
<li>TCP报文段12~23都是ARP模块的输出内容，即Kongming20查询ernest-laptop的MAC地址</li>
</ul>
<blockquote>
<p>在5次重传均失败的情况下，底层的IP和ARP开始接管，知道telnet客户端放弃连接为止</p>
</blockquote>

            <!--[if lt IE 9]><script>document.createElement('audio');</script><![endif]-->
            <audio id="audio" loop="1" preload="auto" controls="controls" data-autoplay="false">
                <source type="audio/mpeg" src="">
            </audio>
            
                <ul id="audio-list" style="display:none">
                    
                        
                            <li title="0" data-url="http://link.hhtjim.com/163/425570952.mp3"></li>
                        
                    
                        
                            <li title="1" data-url="http://link.hhtjim.com/163/425570952.mp3"></li>
                        
                    
                </ul>
            
        </div>
        
    <div id="gitalk-container" class="comment link"
		data-enable="false"
        data-ae="false"
        data-ci=""
        data-cs=""
        data-r=""
        data-o=""
        data-a=""
        data-d="false"
    >查看评论</div>


    </div>
    
</div>


    </div>
</div>
</body>


<script src="//lib.baomitu.com/jquery/1.8.3/jquery.min.js"></script>
<script src="/yi-mark-gitee-io/js/plugin.js"></script>
<script src="/yi-mark-gitee-io/js/typed.js"></script>
<script src="/yi-mark-gitee-io/js/diaspora.js"></script>


<link rel="stylesheet" href="/yi-mark-gitee-io/photoswipe/photoswipe.css">
<link rel="stylesheet" href="/yi-mark-gitee-io/photoswipe/default-skin/default-skin.css">


<script src="/yi-mark-gitee-io/photoswipe/photoswipe.min.js"></script>
<script src="/yi-mark-gitee-io/photoswipe/photoswipe-ui-default.min.js"></script>


<!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
    <!-- Background of PhotoSwipe. 
         It's a separate element as animating opacity is faster than rgba(). -->
    <div class="pswp__bg"></div>
    <!-- Slides wrapper with overflow:hidden. -->
    <div class="pswp__scroll-wrap">
        <!-- Container that holds slides. 
            PhotoSwipe keeps only 3 of them in the DOM to save memory.
            Don't modify these 3 pswp__item elements, data is added later on. -->
        <div class="pswp__container">
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
        </div>
        <!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
        <div class="pswp__ui pswp__ui--hidden">
            <div class="pswp__top-bar">
                <!--  Controls are self-explanatory. Order can be changed. -->
                <div class="pswp__counter"></div>
                <button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
                <button class="pswp__button pswp__button--share" title="Share"></button>
                <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
                <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
                <!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
                <!-- element will get class pswp__preloader--active when preloader is running -->
                <div class="pswp__preloader">
                    <div class="pswp__preloader__icn">
                      <div class="pswp__preloader__cut">
                        <div class="pswp__preloader__donut"></div>
                      </div>
                    </div>
                </div>
            </div>
            <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
                <div class="pswp__share-tooltip"></div> 
            </div>
            <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
            </button>
            <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
            </button>
            <div class="pswp__caption">
                <div class="pswp__caption__center"></div>
            </div>
        </div>
    </div>
</div>






</html>
